package restdom.validation;

import java.util.Iterator;
import java.util.List;

import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.support.DelegatingMessageSource;
import org.springframework.util.Assert;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

public class ValidationErrors extends RuntimeException implements Errors {

	private static final long serialVersionUID = -5090430708631149357L;

	private final Errors errors;

	private MessageSource messageSource = new DelegatingMessageSource();

	public ValidationErrors(Errors errors, MessageSource messageSource) {
		this(errors);
		this.messageSource = messageSource;
	}

	/**
	 * Create a new ValidationErrors instance for an Errors.
	 * 
	 * @param errors
	 *            the Errors instance to wrap
	 */
	public ValidationErrors(Errors errors) {
		Assert.notNull(errors, "Errors must not be null");
		this.errors = errors;
	}

	public String getObjectName() {
		return this.errors.getObjectName();
	}

	public void setNestedPath(String nestedPath) {
		this.errors.setNestedPath(nestedPath);
	}

	public String getNestedPath() {
		return this.errors.getNestedPath();
	}

	public void pushNestedPath(String subPath) {
		this.errors.pushNestedPath(subPath);
	}

	public void popNestedPath() throws IllegalStateException {
		this.errors.popNestedPath();
	}

	public void reject(String errorCode) {
		this.errors.reject(errorCode);
	}

	public void reject(String errorCode, String defaultMessage) {
		this.errors.reject(errorCode, defaultMessage);
	}

	public void reject(String errorCode, Object[] errorArgs,
			String defaultMessage) {
		this.errors.reject(errorCode, errorArgs, defaultMessage);
	}

	public void rejectValue(String field, String errorCode) {
		this.errors.rejectValue(field, errorCode);
	}

	public void rejectValue(String field, String errorCode,
			String defaultMessage) {
		this.errors.rejectValue(field, errorCode, defaultMessage);
	}

	public void rejectValue(String field, String errorCode, Object[] errorArgs,
			String defaultMessage) {
		this.errors.rejectValue(field, errorCode, errorArgs, defaultMessage);
	}

	public void addAllErrors(Errors errors) {
		this.errors.addAllErrors(errors);
	}

	public boolean hasErrors() {
		return this.errors.hasErrors();
	}

	public int getErrorCount() {
		return this.errors.getErrorCount();
	}

	public List getAllErrors() {
		return this.errors.getAllErrors();
	}

	public boolean hasGlobalErrors() {
		return this.errors.hasGlobalErrors();
	}

	public int getGlobalErrorCount() {
		return this.errors.getGlobalErrorCount();
	}

	public List getGlobalErrors() {
		return this.errors.getGlobalErrors();
	}

	public ObjectError getGlobalError() {
		return this.errors.getGlobalError();
	}

	public boolean hasFieldErrors() {
		return this.errors.hasFieldErrors();
	}

	public int getFieldErrorCount() {
		return this.errors.getFieldErrorCount();
	}

	public List getFieldErrors() {
		return this.errors.getFieldErrors();
	}

	public FieldError getFieldError() {
		return this.errors.getFieldError();
	}

	public boolean hasFieldErrors(String field) {
		return this.errors.hasFieldErrors(field);
	}

	public int getFieldErrorCount(String field) {
		return this.errors.getFieldErrorCount(field);
	}

	public List getFieldErrors(String field) {
		return this.errors.getFieldErrors(field);
	}

	public FieldError getFieldError(String field) {
		return this.errors.getFieldError(field);
	}

	public Object getFieldValue(String field) {
		return this.errors.getFieldValue(field);
	}

	public Class getFieldType(String field) {
		return this.errors.getFieldType(field);
	}

	/**
	 * Returns diagnostic information about the errors held in this object.
	 */
	public String getMessage() {
		StringBuffer msg = new StringBuffer();
		Iterator it = getAllErrors().iterator();
		while (it.hasNext()) {
			msg.append("\n").append(
					messageSource.getMessage((MessageSourceResolvable) it
							.next(), null));
		}
		return msg.toString();
	}

	public boolean equals(Object other) {
		return (this == other || this.errors.equals(other));
	}

	public int hashCode() {
		return this.errors.hashCode();
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}

}
